package com.mmall.util;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.util.CellRangeAddress;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by Neo on 3/9/2023.
 */
public class ExcelOutUtilByList {

    static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * @param fileName 文件名，不包含后缀
     * @param path     excel保存路径,不包含文件名
     * @param data     数据list，里面的pojo属性需要有注解@ExcelVaue，才能识别
     * @param sdf2     自定义时间格式化类，传null则使用默认格式 “yyyy-MM-dd HH:mm:ss”
     * @param comment  备注，会显示在标题旁边
     * @return  文件位置
     */
    public static String out(String fileName, String path, List data, SimpleDateFormat sdf2, String comment) {
        if (fileName.contains(".")) {
            fileName = fileName.substring(0, fileName.indexOf("."));
        }

        if (data == null || data.size() < 1) {
            return "没有数据";
        }

        Map indexMap = new HashMap();
        Map titleMap = new HashMap();
        Class<?> aClass = data.get(1).getClass();
        boolean isOk = getValueIndex(new ArrayList(), titleMap, indexMap, aClass);//获取列名和位置
        if (!isOk) {
            return "所有参数都没有@ExcelCell注解，读取列名失败";
        }
        Method[] methods = aClass.getMethods();//获取方法列表

        //创建表格
        HSSFWorkbook wb = new HSSFWorkbook();
        HSSFSheet sheet = wb.createSheet(fileName + 1);

        setHerderRow(fileName,titleMap,wb,comment);//设置标题栏 和样式 第1行
        setCellName(titleMap,indexMap,wb,sheet);//设置列名 第2行

        HSSFCellStyle style = getContent(wb);//获取单元格样式

        for (int i = 0; i < data.size(); i++) {//循环插入数据 从第三行开始插入
            HSSFRow row = sheet.createRow(i + 2);
            Set indexSet = indexMap.keySet();
            Iterator iterator = indexSet.iterator();
            while (iterator.hasNext()) {
                String keyParam = (String) iterator.next();
                int index = (int) indexMap.get(keyParam);

                Object o = data.get(i);
                for (Method method : methods) {
                    if (method.getName().equals(keyParam)) {

                        HSSFCell cell = row.createCell(index - 1);
                        String type = method.getGenericReturnType().toString();

                        try {
                            if (type.equals("int")) {  //取出来的值类型跟excel支持的类型匹配
                                int value = (int) method.invoke(o,null);
                                cell.setCellValue(value);
                            } else if (type.equals("class java.util.Date")) {
                                Date value = (Date) method.invoke(o,null);
                                String format = "";
                                if (sdf2 != null) {
                                    format = sdf2.format(value);
                                } else {
                                    format = sdf.format(value);//Date类先格式化成String再存到cell的value中
                                }
                                cell.setCellValue(format);
                            } else if (type.equals("double")) {
                                double value = (double) method.invoke(o,null);
                                cell.setCellValue(value);
                            } else {
                                String value = (String) method.invoke(o,null);
                                cell.setCellValue(value);
                            }
                            cell.setCellStyle(style);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }

                    }
                }
            }
        }

        //输出文件
        String fileName2 = path + fileName + ".xls";
        File file = new File(fileName2);
        //创建文件输出流
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            //用最开始创建的工作簿.write进行文件写出
            wb.write(fileOutputStream);
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("导出excel异常：" + e.getMessage());
            return "导出excel异常：" + e.getMessage();
        }

        System.out.println("导出成功："  + fileName2);
        return fileName2;
    }


    /**
     * 根据标题栏创建 各个列名
     * @param titleMap 位置-中文标题
     * @param indexMap 属性名-位置
     * @param wb
     * @param sheet
     */
    private static void setCellName(Map titleMap, Map indexMap, HSSFWorkbook wb,HSSFSheet sheet) {
        HSSFRow row = sheet.createRow(1);
        HSSFCellStyle style = wb.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER); // 居中
        style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());// 设置背景色
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);

        style.setBorderBottom(BorderStyle.THIN); //下边框
        style.setBorderLeft(BorderStyle.THIN);//左边框
        style.setBorderTop(BorderStyle.THIN);//上边框
        style.setBorderRight(BorderStyle.THIN);//右边框

        Set set = indexMap.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            String cellName = (String) iterator.next();//英文属性名
            int index = (int) indexMap.get(cellName);//对应位置
            sheet.autoSizeColumn(index-1);//自动列宽
            HSSFCell cell = row.createCell(index - 1);
            cell.setCellValue((String) titleMap.get(index));//将中文名设置进去
            cell.setCellStyle(style);
        }
    }


    /**
     * 设置sheet页的标题栏和样式
     * @param fileName
     * @param titleMap
     * @param wb
     * @param comment
     */
    private static void setHerderRow(String fileName,Map titleMap,HSSFWorkbook wb,String comment) {
        HSSFSheet sheet = wb.getSheetAt(0);
        HSSFCell cell = sheet.createRow(0).createCell(0);
        if (comment != null && comment.length() > 0) {//设置备注
            fileName += "（" + comment +"）";
        }
        cell.setCellValue(fileName);//第一行第一列设置为标题栏
        HSSFCellStyle style = wb.createCellStyle();
        style.setBorderBottom(BorderStyle.THIN); //下边框
        style.setBorderLeft(BorderStyle.THIN);//左边框
        style.setBorderTop(BorderStyle.THIN);//上边框
        style.setBorderRight(BorderStyle.THIN);//右边框
//        style.setFillPattern(FillPatternType.SOLID_FOREGROUND); //设置加粗
        HSSFFont font1 = wb.createFont();
        font1.setColor((short)16);;
        font1.setFontHeightInPoints((short)18);

        style.setFont(font1);
        style.setAlignment(HorizontalAlignment.CENTER);
        sheet.addMergedRegion(new CellRangeAddress(0,0,0,titleMap.size()-1));//合并标题栏
        cell.setCellStyle(style);

    }

    /**
     * 根据要输出的类属性上的注解，获取标题栏和列位置
     * @param count 固定传空list
     * @param titleMap
     * @param indexMap
     * @param classzz
     * @return
     */
    public static boolean getValueIndex(List count,Map titleMap,Map indexMap, Class<?> classzz) {
        boolean flag = true;
        Field[] fields = classzz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            ExcelCell annotation = field.getAnnotation(ExcelCell.class);
            if (annotation == null) {
                continue;
            }
            String name = fields[i].getName();
            name = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);

            indexMap.put(name, annotation.index());
            titleMap.put(annotation.index(),annotation.value());
            count.add(1);
        }
        if (classzz.getSuperclass() != null) {
            getValueIndex(count,titleMap,indexMap,classzz.getSuperclass());
        }

        if (count.size() == 0) {
            flag = false;
            System.out.println("所有参数都没有@ExcelCell注解，读取列名失败");
        }

        return flag;
    }

    /**
     *  设置数据的单元格格式
     * @param wb
     * @return
     */
    public static HSSFCellStyle getContent(HSSFWorkbook wb){
        HSSFCellStyle style = wb.createCellStyle();
        style.setBorderBottom(BorderStyle.THIN); //下边框
        style.setBorderLeft(BorderStyle.THIN);//左边框
        style.setBorderTop(BorderStyle.THIN);//上边框
        style.setBorderRight(BorderStyle.THIN);//右边框
        return style;
    }
}
